#!/usr/bin/python3
# -*- coding:utf-8 -*-
"""
用方法又略显复杂，没有直接用属性这么直接简单。
不是必须加_
变量名和函数名不能够一致，一致将会产生错误
Python内置的@property装饰器就是负责把一个方法变成属性调用的，函数名就是属性名
 @property 必须在前 必须定义在相当于get方法上
"""
import time

"""
class Student(object):

    @property
    def score(self, score):
        if score > 100 or score < 0:
            raise ValueError('score must between 0 ~ 100!')  # 抛出值错误，并自定义错误信息,程序中断
            # print('score must between 0 ~ 100!')
        if 0 <= score <= 100:
            self._score = score

    @score.getter
    def score(self):
        return self._score



class Student(object):

    @score.getter
    def score(self, score):
        if score > 100 or score < 0:
            raise ValueError('score must between 0 ~ 100!')  # 抛出值错误，并自定义错误信息,程序中断
            # print('score must between 0 ~ 100!')
        if 0 <= score <= 100:
            self._score = score

    @property
    def score(self):
        return self._score
"""


class Student1(object):

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self, value):
        if value > 100 or value < 0:
            raise ValueError('score must between 0 ~ 100!')  # 抛出值错误，并自定义错误信息,程序中断
            # print('score must between 0 ~ 100!')
        if 0 <= value <= 100:
            self._score = value


class Student2(object):

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value


class Student3(object):
    """
    不是必须加_ 只是为了与函数名的属性score 进行区分，不一致
    _ 虽然不是私有实例，但要当做私有属性看，可以修改但不要随意修改的属性
    变量名和函数名不能够一致，一致将会产生错误
    """
    @property
    def score(self):
        return self.scor

    @score.setter
    def score(self, value):
        if value > 100 or value < 0:
            raise ValueError('score must between 0 ~ 100!')  # 抛出值错误，并自定义错误信息,程序中断
            # print('score must between 0 ~ 100!')
        if 0 <= value <= 100:
            self.scor = value


class Student4(object):
    """
    __ 表示类的私有属性，外部不能访问
    单数@property修饰函数而伪装成的score属性可以操作
    """
    __slots__ = '__score'

    def __init__(self):
        self.__score = 0

    @property
    def score(self):
        return self.__score

    @score.setter
    def score(self, value):
        if value > 100 or value < 0:
            raise ValueError('score must between 0 ~ 100!')  # 抛出值错误，并自定义错误信息,程序中断
            # print('score must between 0 ~ 100!')
        if 0 <= value <= 100:
            self.__score = value


class Student5(object):
    """
    设置只读的属性age，只用@property 修饰func而不用func.setter
    """
    @property
    def birth(self):
        return self._birth

    @birth.setter
    def birth(self, value):
        self._birth = value

    @property
    def age(self):
        # print(time.localtime())
        s = time.strftime('%Y', time.localtime())
        self._age = int(s) - self._birth
        return self._age


def main():
    # s = Student()
    # s.score = 98
    # print(s.score)
    s1 = Student1()
    s1.score = 60
    print(s1.score)
    s2 = Student2()
    s2._score = 98
    print(s2.score)
    s3 = Student3()
    s3.scor = 100
    print(s3.scor)
    s4 = Student4()
    s4.score = 4    # 报错 Student4' object has no attribute 'scor'
    # print(Student4.__scor)   # 报错 type object 'Student4' has no attribute '__scor'
    print(s4.score)
    print(dir(s4))
    s5 = Student5()
    s5.birth = 1992
    print(s5.birth)
    print(s5.age)


if __name__ == '__main__':
    main()
